import gmpy2
from gmpy2 import mpz

class pffp :
	def __init__(self, basePrime) :
		if basePrime <= 1 :
			raise Exception("The base is not valid")
		
		if gmpy2.is_prime(basePrime) :
			self.basePrime = basePrime
		else :
			raise Exception("The base is not valid")
	
	def pffp_add(self, summand, addend) :
		if summand < 0 or summand >= self.basePrime :
			raise Exception("The summand is not valid")
		if addend < 0 or addend >= self.basePrime :
			raise Exception("The addend is not valid")		
		return gmpy2.t_mod(summand + addend, self.basePrime)
	
	def pffp_sub(self, minuend, subtrahend) :
		if minuend < 0 or minuend >= self.basePrime :
			raise Exception("The minuend is not valid")
		if subtrahend < 0 or subtrahend >= self.basePrime :
			raise Exception("The subtrahend is not valid")	
		temp = minuend - subtrahend
		while temp < 0 :
			temp = temp + self.basePrime
		return gmpy2.t_mod(temp, self.basePrime)

	def pffp_mul(self, multiplicand, multiplier) :
		if multiplicand < 0 or multiplicand >= self.basePrime:
			raise Exception("The multiplicand is not valid")
		if multiplier < 0 or multiplier >= self.basePrime:
			raise Exception("The multiplier is not valid")
		return gmpy2.t_mod(multiplicand * multiplier, self.basePrime)
	
	def pffp_inv(self, inverter) :
		if inverter <= 0 or inverter >= self.basePrime :
			raise Exception("The inverter is not valid")
		u = inverter
		v = self.basePrime
		x1 = mpz('1')
		x2 = mpz('0')
		while u != 1 :
			(q, r) = gmpy2.t_divmod(v, u)
			x = x2 - q * x1
			v = u
			u = r
			x2 = x1
			x1 = x
			#print u
			#print v
			#print x1
			#print x2
		while x1 < 0 :
			x1 = x1 + self.basePrime
		return gmpy2.t_mod(x1, self.basePrime)

			
		

